2023/12/235267字符
数据结构
名词解释
- 数据结构:可以容纳数据的结构(静态),面向存储
- 算法:对数据结构进行处理的方法(动态),面向运算
线性数据结构-数组
数组特性
- 存储在物理空间上是连续的;
- 底层的数组长度是不可变的;
- 数组的变量,指向了数组第一个元素的位置。
var arr = [1, 2, 3, 4, 5, 7, 8]
优点:
- 查询性能好。指定查询某个位置
系统偏移查询:arr[1], arr[2], arr[3] (通过系统偏移查询的方式性能最好)
缺点:
- 如果数组比较大,当系统空间碎片较多的时候,容易存不下;
- 难以添加和删除。
添加或删除会造成数组扩容:
[1, 2, 3, 4, 5, 7, 8, 9, null, null, null, null, null, null, null]
初始指定长度,使性能达到最高
var arr1 = [1, 2, 3, 4, 5]; // 固定内容情况下
var arr2 = new Array(10); // 不固定内容情况下
线性数据结构-链表
链表特性
- 空间不是连续的;
- 每存放一个值,都会多开销一个引用空间。
var a = {1: b} // 链表之间的关系不是嵌套,而是引用
var b = {2: 'string'}
没一个节点,都认为自己是根节点
优点:
- 只要内存足够大,就能存的下,不用担心空间碎片的问题
- 链表的添加和删除非常的容易
缺点:
- 查询速度慢(指定查询某个位置)
- 链表每一个节点都需要创建一个指向 next 的引用,浪费一些空间
节点数据越多,这部分多开销的内存影响越少(一人点火锅与多人点火锅的区别,人越多个人开销越少)
链表创建
function Node (value) {
this.value = value;
this.next = null;
}
var a = new Node(1);
var b = new Node(2);
var c = new Node(3);
var d = new Node(4);
a.next = b;
b.next = c;
c.next = d;
d.next = null;
console.log(a.value);
console.log(a.next.value);
循环遍历
function bianLink (root) {
var temp = root;
while (true) {
if (temp != null) {
console.log(temp.value);
} else {
break;
}
temp = temp.next;
}
}
bianLink(a); //--> 1 2 3 4
递归遍历
// 分治法
function recursion (root) {
if (root == null) return;
console.log(root.value);
recursion(root.next);
}
recursion(a); //--> 1 2 3 4
链表逆置
// 1 2 3 4 5 6 7
function nizhi (root) {
if (root.next.next == null) {
root.next.next = root;
return root.next;
} else {
var result = nizhi(root.next);
root.next.next = root;
root.next = null;
return result;
}
}
var newRoot = nizhi(a);
bianLink(newRoot); //--> 4 3 2 1
双向链表
- 优点:无论给出哪一个节点,都能对整个链表进行遍历
- 缺点:多耗费一个引用的空间,而且构建双向链表比较复杂
function Node (value) {
this.value = value;
this.next = null;
this.pre = null;
}
var node1 = new Node(1);
var node2 = new Node(2);
var node3 = new Node(3);
var node4 = new Node(4);
var node5 = new Node(5);
node1.next = node2;
node2.pre = node1;
node2.next = node3;
node3.pre = node2;
node3.next = node4;
node4.pre = node3;
node4.next = node5;
node5.pre = node4;
二维数组
[ [1, 2], [1, 2], [1, 2], [1, 2] ]
var arr = new Array(4);
for (var i = 0; i < arr.length; i ++) {
arr[i] = new Array(8);
}
console.log(arr); //--> [Array(8), Array(8), Array(8), Array(8)]
二维拓扑结构 / 图
就像是人与人之间的血缘关系,剪不断,理还乱。不受距离、长度等影响
function Node (value) {
this.value = value;
this.neighbor = [];
}
var a = new Node('a');
var b = new Node('b');
var c = new Node('c');
var d = new Node('d');
var e = new Node('e');
a.neighbor.push(b);
a.neighbor.push(d);
a.neighbor.push(e);
b.neighbor.push(c);
b.neighbor.push(e);
c.neighbor.push(a);
c.neighbor.push(d);
console.log(a); //-->
/* {value: 'a',
neighbor: [
Node { value: 'b', neighbor: [Array] },
Node { value: 'd', neighbor: [] },
Node { value: 'e', neighbor: [] }
]
} */
有向无环图 / 树形结构
只有一个根节点,并且没有回路
- 根节点:
- 叶子节点:下面没有其他节点了
- 节点:既不是根节点,也不是叶子节点的普通节点
- 度:树形机构中最多叉的节点的个数
- 深度:树形结构的层数
- 二叉树:度不能超过两个;
- 满二叉树:每个节点都有两个度,所有叶子节点都在最底层;
- 完全二叉树:
- 国内定义:叶子节点都在最后一层或倒数第二层,叶子节点都向左聚拢;
- 国际定义:叶子节点都在最后一层或倒数第二层,叶子节点为两个或一个;
- 子树:每一个节点或叶子节点,都是一颗子树的根节点(一个叶子节点也是子树)。